/**
 * All Rights Reserved , Copyright (C) 2021 , 青岛鼎信通讯股份有限公司
 * <p>
 * MpmProjectPlanController 项目策划
 * <p>
 * 修改纪录 2021-01-07 版本：1.0 wudaliang 创建。
 *
 * @version 版本：1.0
 * @author 作者：wudaliang 创建日期：2021-01-07
 */

package com.topscomm.mpm.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.topscomm.basic.exception.BusinessException;
import com.topscomm.basic.exception.MessageException;
import com.topscomm.basic.exception.ServiceException;
import com.topscomm.mis.pojo.MisDeptArchEntity;
import com.topscomm.mpm.MpmSystemConst;
import com.topscomm.mpm.pojo.*;
import com.topscomm.mpm.service.impl.*;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

import com.topscomm.pub.util.*;
import com.topscomm.pub.vo.Page;
import com.topscomm.pub.vo.Query;

import com.topscomm.tap.ITapService;
import com.topscomm.tap.common.ParameterCache;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.concurrent.ConcurrentUtils;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.topscomm.basic.util.SQLAdapter;
import com.topscomm.cbo.pojo.CboApprovalNodeEntity;
import com.topscomm.cbo.pojo.CboApprovalNodeInsEntity;
import com.topscomm.cbo.service.impl.CboApprovalNodeInsService;
import com.topscomm.mpm.controller.auto.MpmProjectPlanControllerAuto;
import com.topscomm.pub.vo.ResponseResult;
import com.topscomm.tap.common.TapSystemConst.TapOperationTypeEnum;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author: wudaliang
 * @date: 2021-01-07
 * @description:项目策划Controller
 * @modify:
 */
@RestController
@RequestMapping("mpm/projectPlan")
public class MpmProjectPlanController extends MpmProjectPlanControllerAuto implements
    IMpmProjectPlanController {

    @Autowired
    private MpmProjectPolymerizationController mpmProjectPolymerizationController;

    @Autowired
    private MpmProjectMilepostService mpmProjectMilepostService;

    @Autowired
    private MpmProjectService mpmProjectService;
    @Autowired
    private CboApprovalNodeInsService cboApprovalNodeInsService;
    @Autowired
    private MpmProjectTaskService mpmProjectTaskService;
    @Autowired
    private MpmProjectSaleService mpmProjectSaleService;
    @Autowired
    private MpmProjectPlanService mpmProjectPlanService;
    /**
     * @author: wudaliang
     * @date: 2021-01-07
     * @param paraMap
     * @return
     * @description:转换出查询SQL语句
     * @modify:
     */
    @Override
    protected String spellListSql(Map<String, Object> paraMap) {
        this.getUserBean();
        StringBufferProxy sql = new StringBufferProxy();
//		sql.appendSingle(" enabled=1 ");
        sql.appendSingle(" 1=1 ");
        if (paraMap.containsKey("qry_proposalname")) {
            String value = paraMap.get("qry_proposalname").toString();
            if (!StringUtil.isEmpty(value)) {
                sql.appendSingle(" and proposalname like '%{0}%' ", value);
            }
        }
        if (paraMap.containsKey("qry_planner")) {
            String value = paraMap.get("qry_planner").toString();
            if (!StringUtil.isEmpty(value)) {
                sql.appendSingle(" and planner like '%{0}%' ", value);
            }
        }

        if (paraMap.containsKey("qry_projectname")) {
            String value = paraMap.get("qry_projectname").toString();
            if (!StringUtil.isEmpty(value)) {
                sql.appendSingle(" and projectname like '%{0}%' ", value);
            }
        }

        if (paraMap.containsKey("qry_projectcode")) {
            String value = paraMap.get("qry_projectcode").toString();
            if (!StringUtil.isEmpty(value)) {
                sql.appendSingle(" and projectcode  = '{0}' ", value);
            }
        }

        if (paraMap.containsKey("qry_begindocdate")) {
            String value = paraMap.get("qry_begindocdate").toString();
            if (!StringUtil.isEmpty(value)) {
                sql.appendSingle(" and docdate >= {0} ",
                    SQLAdapter.toDateLong(value + " 00:00:00"));
            }
        }
        if (paraMap.containsKey("qry_enddocdate")) {
            String value = paraMap.get("qry_enddocdate").toString();
            if (!StringUtil.isEmpty(value)) {
                sql.appendSingle(" and docdate <= {0}", SQLAdapter.toDateLong(value + " 23:59:59"));
            }
        }
        if (paraMap.containsKey("qry_deptname")) {
            String value = paraMap.get("qry_deptname").toString();
            if (!StringUtil.isEmpty(value)) {
                sql.appendSingle(
                    " and (deptid in ( SELECT id from CboDept where fullname like '%{0}%'))",
                    value);
            }
        }

        if (paraMap.containsKey("qry_state")) {
            String value = paraMap.get("qry_state").toString();
            if (!StringUtil.isEmpty(value)) {
                sql.appendSingle(" and state in ({0})", value);
            }
        }
        if (paraMap.containsKey("qry_enabled")) {
            String value = paraMap.get("qry_enabled").toString();
            if (!StringUtil.isEmpty(value)) {
                sql.appendSingle(" and enabled = {0} ", value);
            }
        }
        if (paraMap.containsKey("qry_where")) {
            String value = paraMap.get("qry_where").toString();
            if (!StringUtil.isEmpty(value)) {
                sql.appendSingle(" and {0}", value);
            }
        }
        if (this.getUserBean().getUser().getAdminlevel() < 1)// 管理员、超级管理员，不控制权限
        {
            String dataPession = service.getDataPermission(TapOperationTypeEnum.Select, "", this.getUserBean());
            if (StringUtil.isEmpty(dataPession))// 默认权限只能看本人，部门负责人为自己的部门和下级部门的数据
            {
//                String deptcodes_header = ConvertUtil.convertToString(this.getUserBean().getUser().getValue("deptcodes_header"));
//                if (StringUtil.isEmpty(deptcodes_header)) {
//                    sql.appendSingle(
//                        " and (usercode = '{0}' or deptcode ='{1}' or deptcode = '{2}' )",
//                        this.getUserBean().getUser().getCode(),
//                        this.getUserBean().getDept().getCode(), this
//                            .getUserBean().getWorkDept().getCode());
//                } else {
//                    sql.appendSingle(
//                        " and (deptcode in ({0})  or usercode = '{1}' or deptcode ='{2}' or deptcode = '{3}' )",
//                        deptcodes_header, this.getUserBean().getUser().getCode(), this
//                            .getUserBean().getDept().getCode(),
//                        this.getUserBean().getWorkDept().getCode());
//                }
            } else// 使用数据权限
            {
                sql.appendSingle(" and {0} ", dataPession);
            }
        }
        return sql.toString();
    }

    /**
     * @author: wudaliang
     * @date: 2021-01-07
     * @param paraMap
     * @return
     * @description:转换出查询SQL语句
     * @modify:
     */
    @Override
    @GetMapping(value = "/refList")
    public ResponseResult<Object> refList(
        @RequestParam(required = false) Map<String, Object> paraMap) {
        return super.refList(paraMap);
    }


    /**
     *
     * @description: 提交审批前
     * @param dataMap
     * @param paraMap
     * @throws Exception
     * @author: wudaliang
     * @date: 2021-01-07
     * @modify:
     */
    @Override
    protected void beforeSubmit(Map<String, Object> dataMap, Map<String, Object> paraMap) throws Exception {
        super.beforeSubmit(dataMap, paraMap);
        // 如果存在短名单任务，需要必填九宫格数据
        if (!ObjectUtil.isEmpty(paraMap.get("dmdtaskid")) && !mpmProjectPlanService.haveSquaredData(ConvertUtil.convertToString(paraMap.get("dmdtaskid")))) {
            throw new ServiceException("加入DMD任务需要填写九宫格数据！");
        }
        // 如果填写了客户决策链分析,则需要必填鱼骨图
        if (!ObjectUtil.isEmpty(paraMap.get("taskidlist"))) {
            List<String> fishTaskList = (List<String>) (paraMap.get("taskidlist"));
            StringBufferProxy taskname = new StringBufferProxy();
            if (!mpmProjectPlanService.haveFishData(fishTaskList, taskname)) {
                throw new ServiceException("任务：" + taskname.toString() + "填写了客户决策链分析，需要填写鱼骨图！");
            }
        }
        StringBufferProxy mailtitle = new StringBufferProxy();
        mailtitle.appendSingle("{0}{1}于{2}提交项目策划申请,单据编号{3}! ",
        		dataMap.get("dispdeptcode"), dataMap.get("username"), DateUtil.dateToString(new Date(), "yyyy-MM-dd"), dataMap.get("docno"));
        dataMap.put("maintitle", mailtitle.toString());
    }

    @PutMapping({"/approval"})
    @Override
    public ResponseResult<Object> approval(@RequestBody(required = false) Map<String, Object> paraMap) {
        try {
            String approvalOpinion = paraMap.get("approvalopinion").toString();
            String approvalType = paraMap.get("approvaltype").toString();
            String nodeInsId = paraMap.get("nodeinsid").toString();
            String backNodeId = ConvertUtil.convertToString(paraMap.get("backnodeid"));
            long nextUserId = 0L;
            if (paraMap.containsKey("nextuserid") && !StringUtil.isEmpty(paraMap.get("nextuserid").toString())) {
                nextUserId = Long.parseLong(paraMap.get("nextuserid").toString());
            }
            if("".equals(approvalOpinion)&&"1".equals(approvalType)){
                approvalOpinion="同意";
            }
            this.service.executeApprove(nodeInsId, new Date(), approvalOpinion, approvalType, backNodeId, this.getUserBean(), nextUserId);
            return ResponseResult.ok("操作成功");
        } catch (Exception var8) {
            return this.handleControllerException(var8);
        }
    }

    /**
     * @author: hudeyong
     * @date: 2021-01-29
     * @param: dataMap
     * @param: paraMap
     * @description: 加载项目信息
     * @return: void
     * @modify:
     */
	@GetMapping(value = "/projectLoadInfo")
	public ResponseResult<Object> milepostLoadInfo(@RequestParam(required = false) Map<String, Object> paraMap) {
		String projectCode = ConvertUtil.convertToString(paraMap.get("projectCode"));
		StringBufferProxy sql = new StringBufferProxy();
		sql.appendSingle("projectCode = '{0}'",projectCode);
		List<MpmProjectEntity> mpmProjectEntities = mpmProjectService.queryByWhere(sql.toString());
		if(mpmProjectEntities.size()==0) {
			throw new ServiceException("没有找到项目信息");
		}
        Map<String, Object> dataMap = mpmProjectEntities.get(0).convertToMap();
        Map<String, Object> dataMapsale = mpmProjectSaleService.queryMapById(ConvertUtil.convertToString(dataMap.get("id")));
        dataMapsale.putAll(dataMap);
        dataMap = dataMapsale;
		paraMap.put("projectinfo", dataMap);
		return ResponseResult.ok(paraMap);
    }


    /**
     * @author: chengengwei
     * @date: 2021-08-20
     * @description: 判断是否是第一次策划
     * @modify:
     */
	@GetMapping(value = "/checkplancount")
	public ResponseResult<Object> checkplancount(@RequestParam(required = false) Map<String, Object> paraMap) {
        String projectcode = ConvertUtil.convertToString(paraMap.get("projectcode"));
        Boolean isadd = ConvertUtil.convertToBoolean(paraMap.get("isadd"));
        StringBufferProxy whereSql = new StringBufferProxy();
        if (isadd) {
            whereSql.appendSingle(" projectcode = '{0}' and state = '9' ", projectcode);
        } else {
            String id = ConvertUtil.convertToString(paraMap.get("id"));
            whereSql.appendSingle(" id = {1} and projectcode = '{0}' and version != 'V1.0' ",
                    projectcode, id);
        }
        paraMap.put("isFirstPlan", this.service.getCount(whereSql.toString()) <= 0);
        return ResponseResult.ok(paraMap);
    }

    /**
     * @author: chengengwei
     * @date: 2021-09-02
     * @description: 查询当前用户可查看的与公开的记录，且项目已结项
     * @modify:
     */
    @GetMapping(value = "/listForOpen")
    public ResponseResult<Object> listForOpen(@RequestParam(required = false) Map<String, Object> paraMap) {
        try {
            if(!paraMap.containsKey("opensid")) {
                paraMap = BaseUtil.decodeSecureMap(paraMap);
            }
            Query query = new Query(paraMap);
            StringBufferProxy whereSql = new StringBufferProxy();
            // 是否公开作为and条件拼接
            whereSql.appendSingle("enabled = 1 and exists (select 1 from mpmproject where mpmproject.projectcode = mpmprojectplan.projectcode and {0}.{1} in ('2', '8') and {2} = '1'",
                    MpmProjectEntity.tableName, MpmProjectEntity.FieldProjectstate, MpmProjectEntity.FieldOpen);
            if (paraMap.containsKey("qry_projectname")) {
                String value = paraMap.get("qry_projectname").toString();
                if (!StringUtil.isEmpty(value))
                    whereSql.appendSingle(" and mpmproject.projectname like '%{0}%' ", value);
            }
            whereSql.appendSingle(" ) ");
            // 搜索条件sql拼接
            if (paraMap.containsKey("qry_proposalname")) {
                String value = paraMap.get("qry_proposalname").toString();
                if (!StringUtil.isEmpty(value))
                    whereSql.appendSingle(" and proposalname like '%{0}%' ", value);
            }
            if (paraMap.containsKey("qry_proposalcode")) {
                String value = paraMap.get("qry_proposalcode").toString();
                if (!StringUtil.isEmpty(value))
                    whereSql.appendSingle(" and proposalcode like '%{0}%' ", value);
            }
            int totalCount = this.service.getCount(whereSql.toString());
            List<Map<String, Object>> tempList = null;
            if (query.getPageSize() > 0) {
                tempList = this.service.queryMapForPage(whereSql.toString(), query.getCurrentPage(), query.getPageSize(),
                        query.getSidx(), query.getSord());
            } else
                tempList = this.service.queryMapByWhere(whereSql.toString());
            if (CollectionUtils.isEmpty(tempList)) {
                return ResponseResult.ok(new Page(tempList, totalCount, query.getPageSize(), query.getCurrentPage()));
            }
            // 获取项目相关信息
            this.service.getProjectInfo(tempList);
            this.getCustomerTaskForList(tempList,paraMap);
            Page page = new Page(tempList, totalCount, query.getPageSize(), query.getCurrentPage());
            return ResponseResult.ok(page);
        } catch (Exception ex) {
            return handleControllerException(ex);
        }
    }


    /**
     * @Title: list
     * @description:查询A级项目是否存在新客户决策分析
     * @author: houyuhang
     * @date: 2022年03月18日
     * @modify:
     */
    private void getCustomerTaskForList(List<Map<String, Object>> tempList, Map<String, Object> paraMap) {
        // 获取客户决策分析
        String projectcode = tempList.stream().map(item -> "'" + ConvertUtil.convertToString(item.get("projectcode")) + "'").collect(Collectors.joining(","));
        if (StringUtil.isEmpty(projectcode)) {
            return;
        }
        StringBufferProxy sql = new StringBufferProxy();
        if (paraMap.containsKey("qry_needsupport") && !ObjectUtil.isEmpty(paraMap.get("qry_needsupport"))) {
            String needsupport = ConvertUtil.convertToString(paraMap.get("qry_needsupport"));
            sql.appendSingle(" {0} = '{1}' and ", MpmProjectTaskEntity.FieldNeedsupport, needsupport);
        }
        List<Map<String, Object>> mpmSystemTasknameList = datacodeCache.getCodeListMap("MpmSystemTaskname", "", "sortcode");
        String taskName = mpmSystemTasknameList.stream().map(item -> "'" + ConvertUtil.convertToString(item.get("name")) + "'").collect(Collectors.joining(","));
        sql.appendSingle(" projectcode in ({0}) and state = 9 and {1} is not null and {2} in ({3}) ", projectcode, MpmProjectTaskEntity.FieldPost, MpmProjectTaskEntity.FieldTaskname, taskName);
        List<MpmProjectTaskEntity> customerTaskList = mpmProjectTaskService.queryByWhere(sql.toString());
        // 客户决策分析按照projectcode分类
        Map<String, List<MpmProjectTaskEntity>> customerTaskMap = customerTaskList.stream().collect(Collectors.groupingBy(MpmProjectTaskEntity::getProjectcode));
        for (Map<String, Object> temp : tempList) {
            List<MpmProjectTaskEntity> res = customerTaskMap.get(ConvertUtil.convertToString(temp.get("projectcode")));
            if (CollectionUtil.isEmpty(res)) {
                temp.put("disabledexpand", true);
            } else {
                temp.put("disabledexpand", false);
            }
        }
    }

    /**
     * @author: chengengwei
     * @date: 2021-09-02
     * @description: 查询当前用户可查看的与公开的记录，且项目已结项
     * @modify:
     */
    @GetMapping(value = "/loadPlanInfo")
    public ResponseResult<Object> loadPlanInfo(@RequestParam(required = false) Map<String, Object> paraMap) {
        try {
        	String milepostcode = ConvertUtil.convertToString(paraMap.get("milepostcode"));
        	StringBufferProxy sql = new StringBufferProxy();
        	sql.appendSingle("id = (select max(planid) from {0} where operatecode = '{1}' and enabled = 1 )",MpmProjectMilepostEntity.tableName, milepostcode);
        	List<MpmProjectPlanEntity> mpmProjectPlanEntities = this.service.queryByWhere(sql.toString());
        	boolean key = true;
        	if(mpmProjectPlanEntities.size()>0 && mpmProjectPlanEntities.get(0).getState() == 9) {
        		key = false;
        	}
            return ResponseResult.ok(key);
        } catch (Exception ex) {
            return handleControllerException(ex);
        }
    }
    /**
     * @author: houyuhang
     * @date: 2022-03-11
     * @description: 查询项目是否为A级（非电商、其他）项目
     * @modify:
     */
    @GetMapping(value = "/checkProjectALevel")
    public ResponseResult<Object> checkProjectALevel(@RequestParam(required = false) Map<String, Object> paraMap) {
        try {
            Map<String, Object> resMap = new HashMap<>();
            String projectcode = ConvertUtil.convertToString(paraMap.get("projectcode"));
            resMap.put("alevelflag", mpmProjectMilepostService.judgeProjectALevel(projectcode));
            resMap.put("managerflag", mpmProjectPlanService.judgeProvinceManager(projectcode));
            return ResponseResult.ok(resMap);
        } catch (Exception ex) {
            return ResponseResult.error("获取项目等级出错，请联系管理员!");
        }
    }
    /**
     * @Title:
     * @description: 重写datacodelist
     * @param paraMap
     * @return
     * @author: houyuhang
     * @date: 2022年04月06日
     * @modify:
     */
    @Override
    @GetMapping(value = "/dataCodeList")
    public ResponseResult<Object> dataCodeList(@RequestParam(required = false) Map<String, Object> paraMap) {
        ResponseResult<Object> res = super.dataCodeList(paraMap);
        Map<String, Object> codeMap = (Map<String, Object>) res.getResult();
        List<Map<String, Object>> mpmSystemTasknameList = datacodeCache.getCodeListMap("MpmSystemTaskname", "", "sortcode");
        codeMap.put("mpmsystemtasknameList", mpmSystemTasknameList);
        return ResponseResult.ok(codeMap);
    }
    /**
     * @author: houyuhang
     * @date: 2023-02-13
     * @description: 查询项目是否存在未审批完成的策划书
     * @modify:
     */
    @GetMapping(value = "/checkPlanUnfinish")
    public ResponseResult<Object> checkPlanUnfinish(@RequestParam(required = false) Map<String, Object> paraMap) {
        try {
            String projectcode = ConvertUtil.convertToString(paraMap.get("projectcode"));
            boolean flag = mpmProjectPlanService.checkPlanUnfinish(projectcode);
            return ResponseResult.ok(flag);
        } catch (Exception ex) {
            return ResponseResult.error("获取策划书审批状态出错，请联系管理员!");
        }
    }

    /**
     * 导出大数据量的excel
     *
     * @description:
     * @param paraMap
     * @param request
     * @param response
     * @author: hdy
     * @date: 2023年2月15日
     * @modify:
     */
    @PostMapping(value = "/exportBigExcel")
    public ResponseResult<Object> exportBigExcel(@RequestBody(required = false) Map<String, Object> paraMap,
                                                 HttpServletRequest request, HttpServletResponse response) {
        paraMap = BaseUtil.decodeSecureMap(paraMap);
        String cols = ConvertUtil.convertToString(paraMap.get("cols"));
        paraMap = BaseUtil.decodeSecureMap(paraMap);
        List<Map<String, Object>> tempList = this.service.queryMap(paraMap,"queryMilePostAndTask");
        StringBufferProxy sql = new StringBufferProxy();
        mpmProjectTaskService.setDispFields(tempList);
        String fileName = ConvertUtil.convertToString(paraMap.get("fileName"));
        try {
            // 导出数据
            exportExcelXlsx(response, this.service, tempList, "", fileName, cols,
                    this.getUserBean().getUser().getId());
            return null;
        } catch (Exception ex) {
            return handleControllerException(ex);
        }
    }

    /**
     * 导出excel，或者直接导出流文件，或者后台定时任务生成
     *
     * @description:
     * @param cboService
     * @param paraMap
     * @param queryMybatisMapper
     * @param fileName
     * @param columns
     * @return
     * @author: donghang
     * @date: 2020年5月26日上午10:52:17
     * @modify:
     */
    @SuppressWarnings("rawtypes")
    public static final void exportExcelXlsx(HttpServletResponse response, ITapService cboService,
                                             List<Map<String, Object>> templist, String queryMybatisMapper, String fileName, String columns, long userId)
            throws Exception {
        if (ConvertUtil.convertToString(fileName).length() == 0) {
            fileName = "导出数据表.xlsx";
        }
        if (!ConvertUtil.convertToString(fileName).contains("xlsx")) {
            fileName = fileName + ".xlsx";
        }
        InputStream inputStream = null;
        if (ConvertUtil.convertToString(queryMybatisMapper).length() == 0) {// 没有传入mybatis的mapper
            int totalCount = templist.size();
            int exportMaxCount = ParameterCache.getIntValue("CboExcelInDirectMaxCount", 1000000);
            if (totalCount > exportMaxCount) {
                throw new BusinessException("最大允许导出" + exportMaxCount + "行");
            }
            // 是否直接相应，数量少的直接相应
            int exportDirectMaxCount = ParameterCache.getIntValue("CboExcelDirectMaxCount", 20000);
            boolean isResponse = totalCount < exportDirectMaxCount ? true : false;
            if (isResponse == true) {
                inputStream = exportExeclXlsx(templist, columns.split(","));
            }
        } else {
            int exportMaxCount = ParameterCache.getIntValue("CboExcelInDirectMaxCount", 1000000);
            if (templist.size() > exportMaxCount) {
                throw new BusinessException("最大允许导出" + exportMaxCount + "行");
            }
            // 是否直接相应，数量少的直接相应
            int exportDirectMaxCount = ParameterCache.getIntValue("CboExcelDirectMaxCount", 20000);
            boolean isResponse = templist.size() < exportDirectMaxCount ? true : false;
            if (isResponse == true) {
                inputStream = exportExeclXlsx(templist, columns.split(","));
            }
        }
        if (inputStream != null) {// 文件流直接相应
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setHeader("istaskexport", "0");
            // 需要添加否则前台得不到istaskexport
            response.setHeader("Access-Control-Expose-Headers", "istaskexport");
            response.setHeader("FileName", URLEncoder.encode(fileName, "utf-8"));
            response.setHeader("Access-Control-Expose-Headers", "FileName");
            OutputStream outStream = response.getOutputStream();
            byte[] bytes = new byte[2048];
            int len;
            while ((len = inputStream.read(bytes)) != -1) {
                outStream.write(bytes, 0, len);
            }
            inputStream.close();
        }
    }

    public static InputStream exportExeclXlsx(List<Map<String, Object>> listMap, String[] columns) throws Exception {
        int rowIndex = 0;
        XSSFWorkbook wb = new XSSFWorkbook();
        // 表头格式
        XSSFCellStyle headCellStyle = wb.createCellStyle();
        headCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 上下居中
        headCellStyle.setAlignment(HorizontalAlignment.CENTER); // 居中
        XSSFFont font = wb.createFont();
        font.setFontName(I18nUtil.getMessage("tap.common.songti"));
        font.setBold(true);
        headCellStyle.setFont(font);
        // 表行格式
        XSSFCellStyle lineCellStyle = wb.createCellStyle();
        lineCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 上下居中
        lineCellStyle.setAlignment(HorizontalAlignment.CENTER);
        lineCellStyle.setBorderLeft(BorderStyle.THIN);
        lineCellStyle.setBorderRight(BorderStyle.THIN);
        lineCellStyle.setBorderTop(BorderStyle.THIN);
        lineCellStyle.setBorderBottom(BorderStyle.THIN);
        lineCellStyle.setWrapText(true);
        // 表头
        XSSFSheet sheet = wb.createSheet("sheet1");
        XSSFRow row = sheet.createRow(rowIndex++);
        for (int i = 0; i < columns.length; i++) {
            XSSFCell cell = row.createCell(i);
            cell.setCellStyle(headCellStyle);
            String[] kv = columns[i].split(";");
            String value = kv[1];
            cell.setCellValue(value);
        }
        String rowInfo = "";
        if(listMap.size()>0){
            rowInfo = ConvertUtil.convertToString(listMap.get(0).get("id"));
        }
        int startindex = 1;
        int endindex = 0;
        // 表行
        for (Map<String, Object> data : listMap) {
            // 合并行
            if(!rowInfo.equals(ConvertUtil.convertToString(data.get("id"))) ||
                    (rowInfo.equals(ConvertUtil.convertToString(data.get("id"))) && endindex == listMap.size()-1)){
                if(rowInfo.equals(ConvertUtil.convertToString(data.get("id"))) && endindex == listMap.size()-1){
                    endindex++;
                }
                if(endindex>startindex){
                    sheet.addMergedRegion(new CellRangeAddress(startindex, endindex, 0, 0));
                    sheet.addMergedRegion(new CellRangeAddress(startindex, endindex, 1, 1));
                    sheet.addMergedRegion(new CellRangeAddress(startindex, endindex, 2, 2));
                    sheet.addMergedRegion(new CellRangeAddress(startindex, endindex, 3, 3));
                }
                startindex = endindex + 1;
                rowInfo = ConvertUtil.convertToString(data.get("id"));
            }
            endindex++;
            row = sheet.createRow(rowIndex++);
            for (int i = 0; i < columns.length; i++) {
                String[] kv = columns[i].split(";");
                String key = kv[0];
                XSSFCell cell = row.createCell(i);
                String value = "";
                if (!StringUtil.isEmpty(key) && data.get(key) != null) {
                    if (data.get(key) instanceof Date) {
                        value = DateUtil.dateToString((Date) data.get(key));
                        cell.setCellValue(value);
                    } else if (data.get(key) instanceof BigDecimal || data.get(key) instanceof Double
                            || data.get(key) instanceof Float) {
                        Double d = ConvertUtil.convertToDouble(data.get(key));
                        cell.setCellValue(d);
                    } else {
                        value = data.get(key).toString();
                        cell.setCellValue(value);
                    }
                }
                cell.setCellStyle(lineCellStyle);
            }
        }
        // 自适应列
        int columnCount = columns.length;
        for (int i = 0; i < columnCount; i++) {
            sheet.autoSizeColumn(i);
            int colWidth = sheet.getColumnWidth(i) * 17 / 10;
            if (colWidth < 255 * 256) {
                sheet.setColumnWidth(i, colWidth);
            } else {
                sheet.setColumnWidth(i, 6000);
            }
        }
        // 生成流
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        InputStream is = null;
        try {
            wb.write(os);
            os.flush();
            byte[] content = os.toByteArray();
            is = new ByteArrayInputStream(content);
        } catch (Exception ex) {
            if (os != null) {
                os.close();
                os = null;
            }
            if (wb != null) {
                wb.close();
            }
        }
        return is;
    }
}

